package com.apestech.framework.sql.table;

import com.apestech.api.tables.SequenceManage;
import com.apestech.framework.db.SqlSession;
import com.apestech.framework.dictionary.modul.Table;
import com.apestech.framework.json.JSON;
import com.apestech.framework.json.JSONArray;
import com.apestech.framework.json.JSONObject;
import com.apestech.framework.sql.SqlUtil;
import com.apestech.framework.sql.callback.MasterSaveInter;
import com.apestech.framework.sql.lib.TableSql;
import com.apestech.framework.util.DBPub;
import com.apestech.framework.util.callback.IdKeyCallback;
import com.apestech.framework.util.callback.SpiltStrCallback;
import com.apestech.framework.xml.plugin.modul.SpecialField;
import com.apestech.framework.xml.table.modul.MasterTable;
import com.apestech.framework.xml.table.modul.Tables;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * @author hup
 * @create 2019-01-02-11:45
 */
public class MasterTableSave extends SqlUtil {
    private SqlSession session;
    private Tables table;
    private MasterTable mastertable;
    private JSONObject data;
    private JSONArray datalist;
    private String tabname;
    private JSONObject keydata;
    private String keyField;
    private String keyType;
    private boolean insert=false;
    private JSONObject detailMap;
    private MasterSaveInter saveInter;
    private IdKeyCallback idKeyCallback;
    private String masterKey;

    public MasterTableSave(SqlSession session, TableSql ddlsql, JSONObject data) throws Exception {
        this.session=session;
        table=ddlsql.getTable();
        mastertable=table.getMaster();
        tabname=table.getMasterTableId();
        Table dicTable=this.session.getDictTable(tabname);
        keyField=dicTable.getPkKey().getPkColumn();
        keyType=dicTable.getClassName(keyField);
        if(data.get(tabname) instanceof JSONArray) this.datalist= (JSONArray) data.get(tabname);
        else {
            this.data= (JSONObject) data.get(tabname);
            if(this.data==null) this.data=data;
        }
        saveInter=table.getSaveInter();
        if(saveInter!=null){
            this.data=saveInter.getJSON(this.data);
        }
    }

    public MasterTableSave(SqlSession session, MasterTable mastertable, Object data, String tabname, JSONObject keydata, boolean insert, JSONObject detailMap, MasterSaveInter saveInter, String masterKey) throws Exception {
        this.session=session;
        this.mastertable=mastertable;
        if(data instanceof Map) this.data= JSON.toJSON(data);
        else this.datalist= JSON.toJSONArray(data);
        this.tabname=tabname;
        this.keydata=keydata;
        this.insert=insert;
        this.detailMap=detailMap;
        this.saveInter=saveInter;
        this.masterKey=masterKey;
    }

    public MasterSaveInter getSaveInter() {
        return saveInter;
    }

    public void setIdKeyCallback(IdKeyCallback idKeyCallback) {
        this.idKeyCallback = idKeyCallback;
    }

    public Object save() throws Exception {
        Object idValue=null;
        if(data!=null){
            if(keyField==null){
                if(!insert) {
                    detailMap.put("ZTAB_KEY",masterKey);
                    session.getForUpdate().deleteTable(tabname, detailMap);  //detailMap
                }
            }
            idValue=saveTableJSON(data, idValue);
        }
        else {
            if(keyField==null){
                if(!insert) {
                    keydata.put("ZTAB_KEY",masterKey);
                    session.getForUpdate().deleteTable(tabname, keydata);  //detailMap
                    //session.getForUpdate().update("DELETE FROM "+tabname+" WHERE 1=1 AND ID=#{ID}", kmap);  //detailMap
                }
            }
            int len=datalist.size();
            for(int i=0; i<len; i++){
                JSONObject p=null;
                if(saveInter!=null) {
                    p=saveInter.getJSON(datalist.get(i));
                }
                if(p==null) {
                    p=datalist.get(i);
                }
                JSONObject p1=new JSONObject();
                p1.putAll(detailMap);
                p1.putAll(p);
                idValue=saveTableJSON(p1, idValue);
            }
        }
        return idValue;
    }

    private Object saveTableJSON(JSONObject param, Object idValue) throws Exception {
        Table tab=null;
        if(keydata!=null) param.putAll(keydata);
        if(keyField!=null){
            if(param.get(keyField)==null || "".equals(param.getString(keyField).trim())){
                insert=true;
                if(idKeyCallback!=null){
                    idValue=idKeyCallback.getKey(tabname);
                } else {
                    if(table!=null && table.getSeq()!=null){
                        SequenceManage sequenceManage=new SequenceManage(session);
                        sequenceManage.createSeq(table.getSeq(), true);
                        String idField=table.getSeq().getIdField();
                        if(param.get(idField)==null){
                            if("java.lang.String".equals(keyType)) idValue=sequenceManage.getNextNumByStr(tabname);
                            else idValue=sequenceManage.getNextNum(tabname);
                        }
                    }
                }
                if(idValue!=null){
                    param.put(keyField, idValue);
                }
            } else {
                if(idValue==null) idValue=param.get(keyField);
            }
            detailMap=new JSONObject();
            detailMap.put(table.getMasterKey(), param.get(keyField));
            detailMap.put("table_key","");
            detailMap.put("autoCompletion","1");
            if(insert) session.getForUpdate().insertTable(tabname, param);
            else {
                SpecialField.Field sysField= session.getSpecialField();
                JSONObject mparam=new JSONObject();
                mparam.putAll(param);
                mparam.put("table_time_field", sysField.getTimestamp());
                mparam.put("table_time_control", "1");
                mparam.put(sysField.getTimestamp()+"_NEW","SYSDATE");
                int t=session.getForUpdate().updateTable(tabname, mparam);
                if(t==0){
                    throw new Exception("该数据已被修改或者删除，不允许继续操作！");
                }
            }
        } else {
            try{
                tab=session.getDictTable(tabname);
                if(tab!=null){
                    session.getForUpdate().insertTable(tabname, param);
                }
            } catch (Exception e){
                String msg=e.getMessage();
                if(msg.indexOf("PK_"+tabname)>=0){
                    String pk=null;
                    if(tab.getPkKey()!=null){
                        pk=tab.getPkKey().getPkColumn();
                    }
                    if(pk!=null && !"".equals(pk)){
                        if(pk.indexOf(";")<0){
                            msg="该明细项只允许输入一条数据！";
                        } else {
                            final String[] str = {""};
                            Table finalTab = tab;
                            execSplitStr(pk, ";", new SpiltStrCallback() {
                                @Override
                                public void exec(String id) throws Exception {
                                    if(!"".equals(str[0])){
                                        str[0]=str[0]+",";
                                    }
                                    str[0] = str[0] + finalTab.getField(id).getRemarks()+":"+"["+param.getString(id)+"]";
                                }
                            });
                            msg="请检查，明细项数据存在输入重复————"+str[0];
                        }
                    }
                    throw new Exception(msg);
                } else { //if(msg.indexOf("NULL")>=0){
                    throw new Exception(msg);
                }
            }
        }
        ArrayList<String> klist=param.getKeylist();
        int len=klist.size();
        for(int i=0; i<len; i++){
            String key=klist.get(i);
            if(param.get(key) instanceof List || param.get(key) instanceof Map){
                JSONObject p=new JSONObject();
                p.putAll(param);
                p.putAll(detailMap);
                p.remove(key);
                MasterTableSave mt=new MasterTableSave(session, mastertable,
                        param.get(key), key,
                        getKeyValue(session, tabname, key, param),
                        insert, p, saveInter, keyField);
                mt.save();
            }
        }
        return idValue;
    }

}
